#pragma once

#include <MyFC/Widget.h>
#include <MyFC/Container.h>
#include <MyFC/Timer.h>	 
#include <MyFC/ScrollBar.h>	 

#include "Types.h"
#include "DLL.h"
#include "Sequence.h"
#include "TimeRuler.h"
#include "Navigator.h"
#include "ThumbLine.h"
#include "TimeSlider.h"
#include "TimeScaleIn.h"
#include "TimeScaleOut.h"

namespace My {

/**
 * Base class for timeline controls
 */
class DLL_API Timeline :
	public Widget, 
	public Container,
	public EventDispatcher
{
public:
	Timeline();
	~Timeline();
public:
	Navigator & GetNavigator();
	ThumbLine & GetThumbLine();
	TimeRuler & GetTimeRuler();
public:
	virtual void ProcessEvent(My::Event & e);
	virtual void HandleResize(int sx, int sy);
	virtual CSize GetPreferredSize() const;
	virtual void LayoutControls();
public:
	Sequence * GetSequence() const;
	void SetSequence(Sequence *);
public:
	bool IsEmpty() const;
	/// returns the internal CF
	int GetCurrentFrame() const;
	/// sets the internal CF
	void SetCurrentFrame(int);
	/// sets the Sequence's CF equal to the internal CF
	void UpdateCurrentFrame();

	Span GetWorkArea() const;
	void SetWorkArea(Span);
	void UpdateWorkArea();

	double GetTimeScale() const;
	void SetTimeScale(double);
	double GetMinTimeScale() const;
	double GetMaxTimeScale() const;
	
	double GetTimeOffset() const;
	void SetTimeOffset(double);
	
	double GetTimePage() const;
	double GetTimeRange() const;

	/// returns the width of the time-mapped area
	virtual int GetXPage() const;
	int GetXRange() const;
	int GetXOffset() const;

	void SetTimeAutoScroll(int);
	void OnAutoScroll(bool mouseMove);

	// Actual time-space mapping
	double XToTime(int) const;
	int TimeToX(double) const;

	int GetGap() const;
// Events:
public:
	class Event : public My::Event {
	public:
		Timeline &	m_Timeline;
		Event(Timeline & t) : m_Timeline(t) { }
	};
	class Attached : public Event {
	public:
		Attached(Timeline & t) : Event(t) { }
	};
	class Detached : public Event {
	public:
		Detached(Timeline & t) : Event(t) { }
	};
	class CurrentFrameChange : public Event {
	public:
		CurrentFrameChange(Timeline & t) : Event(t) { }
	};
	class WorkAreaChange : public Event {
	public:
		WorkAreaChange(Timeline & t) : Event(t) { }
	};
	class TimeScaleChange : public Event {
	public:
		TimeScaleChange(Timeline & t) : Event(t) { }
	};
	class TimeOffsetChange : public Event {
	public:
		TimeOffsetChange(Timeline & t) : Event(t) { }
	};
private:
	void UpdateTimeScale()
		{ SetTimeScale(m_TimeScale); }
	void UpdateTimeOffset()
		{ SetTimeOffset(m_TimeOffset); }
	void SetXOffset(int);
	void UpdateXScrollBar();
	void OnTimeScroll(UINT nCode, UINT nPos);
	void OnCurrentFrameChanged();
	void OnWorkAreaChanged();
	void OnStartChanged();
	void OnDurationChanged();
protected:
	virtual void OnOpen();
	virtual void OnClose();
protected:
	Timer			m_AutoScroll;
	ScrollBar		m_XScrollBar;
	Navigator		m_Navigator;
	ThumbLine		m_ThumbLine;
	TimeRuler		m_TimeRuler;
	TimeSlider		m_TimeSlider;
	TimeScaleIn		m_ScaleIn;
	TimeScaleOut	m_ScaleOut;
private:
	Sequence *	m_pSequence;
	int			m_CurrentFrame;
	Span		m_WorkArea;
	int			m_Gap;
	double		m_TimeScale; // px per frame
	double		m_TimeOffset;
	int			m_XAutoScroll;
	int			m_TimeScrollLine;
};

} // My

#include "Impl/Timeline.inl"
